#include <Windows.h>
#include <gl/GL.h>
#include <iostream>

#include "Engine/Render.h"
#include "Common/Utility.h"

namespace CNWoofer
{
	namespace Engine
	{
		Render::Render( void )
		{

		}

		Render::~Render( void )
		{

		}

		sf::Shader* Render::LoadShader( std::string name, std::string vert, std::string frag )
		{
			sf::Shader* shdr = new sf::Shader;

			if( !shdr->loadFromFile( vert, frag ) )
			{
				delete shdr;

				std::cout << "Unable to load shader: " << name << " (" << vert << ", " << frag << ")" << std::endl;
				return NULL;
			}
			
			std::cout << "Loaded shader: " << name << " (" << vert << ", " << frag << ")" << std::endl;

			mShaders[name] = shdr;

			return shdr;
		}

		void Render::EnableShader( std::string name )
		{
			if( mShaders[name] )
			{
				mRenderState.shader = mShaders[name];
			}
		}

		void Render::DisableShader( void )
		{
			mRenderState.shader = NULL;
		}
	
		void Render::SetWindow( sf::RenderWindow* window )
		{
			if( window )
				mWindow = window;

			mView = window->getView();

			GenScreenVecs();	
		}

		void Render::SetFont( sf::Font* font )
		{
			if( font )
				mText.setFont( *font );
		}

		void Render::MoveView( float x, float y )
		{
			mView.move( x, y );

			mWindow->setView( mView );
			
			GenScreenVecs();
		}

		void Render::PreRender( void )
		{
			glClearColor( 0.0f, 0.9f, 1.0f, 1.0f );
			glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
		}

		void Render::PostRender( void )
		{
			mWindow->display();
		}
	
		void Render::DrawQuad( sf::Texture* tex, sf::Vector2f pos, float scale )
		{
			sf::Sprite spr;

			spr.setPosition( pos );
			spr.setTexture( *tex );
			spr.setScale( sf::Vector2f( scale, scale ) );

			mWindow->draw( spr, mRenderState );
		}

		void Render::DrawString( std::string str, sf::Vector2f pos )
		{
			mText.setString( str );
			mText.setPosition( pos );

			mWindow->draw( mText );
		}

		void Render::DrawMap( Map* map )
		{
			std::list<Tile*>::iterator i = map->Tiles.begin();

			while( i != map->Tiles.end() )
			{
				int x = (*i)->RealX;
				int y = (*i)->RealY;
				int tsize = map->TileSize;

				if( IsOnScreen( sf::Vector2f( (float)x, (float)y ), sf::Vector2f( (float)(x + tsize), (float)(y + tsize) ) ) )
				{
					DrawQuad( (*i)->Texture, sf::Vector2f( (float)(*i)->RealX, (float)(*i)->RealY ), 0.5 );
				}

				i++;
			}
		}

		bool Render::IsOnScreen( sf::Vector2f tl, sf::Vector2f br )
		{
			if ( Common::AABB( tl, br, ScreenTL, ScreenBR ) )
			{
				return true;
			}

			return false;
		}

		void Render::GenScreenVecs( void )
		{
			int width = mWindow->getSize().x;
			int height = mWindow->getSize().y;

			ScreenTL = sf::Vector2f( (mView.getCenter().x - (float)width / 2) - 5, 
				(mView.getCenter().y - (float)height / 2) - 5 );

			ScreenBR = sf::Vector2f( (mView.getCenter().x + (float)width / 2) + 5, 
				(mView.getCenter().y + (float)height / 2) + 5  );
		}
	}
}